package qyWechat

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

/*
	创建群聊
	发送消息
*/

const (
	createAppChat = "https://qyapi.weixin.qq.com/cgi-bin/appchat/create"
	updateAppChat = "https://qyapi.weixin.qq.com/cgi-bin/appchat/update"
	sendAppChat   = "https://qyapi.weixin.qq.com/cgi-bin/appchat/send"
)

type AppChat struct {
	Name        string   `json:"name"`
	Owner       string   `json:"owner"`
	UserList    []string `json:"userlist,omitempty"`
	AddUserList []string `json:"add_user_list,omitempty"`
	DelUserList []string `json:"del_user_list,omitempty"`
	ChatId      string   `json:"chatid,omitempty"`
}

type Result struct {
	ErrCode int    `json:"errcode"`
	ErrMsg  string `json:"errmsg"`
	ChatId  string `json:"chatid,omitempty"`
}

// 创建群聊
func (w *QyWechat) CreateAppChatByString(str string) (chatId string, err error) {
	var count = 0
x:
	token, err := w.getAccessToken()
	if err != nil {
		return
	}
	r, err := http.Post(createAppChat+"?access_token="+token, "application/x-www-form-urlencoded", strings.NewReader(str))
	if err != nil {
		return
	}
	defer r.Body.Close()
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	var m Result
	err = json.Unmarshal(b, &m)
	if err != nil {
		return
	}
	if m.ErrCode != 0 {
		if m.ErrCode == 40014 || m.ErrCode == 42001 {
			w.httpGetAccessToken()
			if count == 0 {
				count++
				goto x
			}
		}
		return chatId, errors.New(fmt.Sprint(m.ErrCode) + "-" + m.ErrMsg)
	}
	chatId = m.ChatId
	return
}
func (w *QyWechat) CreateAppChat(name, owner string, users []string) (chatId string, err error) {
	b, err := json.Marshal(AppChat{Name: name, Owner: owner, UserList: users})
	if err != nil {
		return
	}
	return w.CreateAppChatByString(string(b))
}

// 修改群聊
func (w *QyWechat) UpdateAppChatByString(str string) (err error) {
	var count = 0
x:
	token, err := w.getAccessToken()
	if err != nil {
		return
	}
	r, err := http.Post(updateAppChat+"?access_token="+token, "application/x-www-form-urlencoded", strings.NewReader(str))
	if err != nil {
		return
	}
	defer r.Body.Close()
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	var m Result
	err = json.Unmarshal(b, &m)
	if err != nil {
		return
	}
	if m.ErrCode != 0 {
		if m.ErrCode == 40014 || m.ErrCode == 42001 {
			w.httpGetAccessToken()
			if count == 0 {
				count++
				goto x
			}
		}
		return errors.New(fmt.Sprint(m.ErrCode) + "-" + m.ErrMsg)
	}
	return
}
func (w *QyWechat) UpdateAppChat(chatId, name, owner string, addUsers []string, delUsers []string) (err error) {
	b, err := json.Marshal(AppChat{ChatId: chatId, Name: name, Owner: owner, AddUserList: addUsers, DelUserList: delUsers})
	if err != nil {
		return
	}
	return w.UpdateAppChatByString(string(b))
}

/*
	群聊发送消息
*/

func (w *QyWechat) sendAppChatByte(data []byte) (err error) {
	var count = 0
x:
	token, err := w.getAccessToken()
	if err != nil {
		return
	}
	r, err := http.Post(sendAppChat+"?access_token="+token, "application/x-www-form-urlencoded", bytes.NewReader(data))
	if err != nil {
		return
	}
	defer r.Body.Close()
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return
	}
	var m Result
	err = json.Unmarshal(b, &m)
	if err != nil {
		return
	}
	if m.ErrCode != 0 {
		if m.ErrCode == 40014 || m.ErrCode == 42001 {
			w.httpGetAccessToken()
			if count == 0 {
				count++
				goto x
			}
		}
		return errors.New(fmt.Sprint(m.ErrCode) + "-" + m.ErrMsg)
	}
	return
}

func (w *QyWechat) SendAppChatString(str string) (err error) {
	return w.sendAppChatByte([]byte(str))
}

func (w *QyWechat) sendAppChatMsg(req interface{}) (err error) {
	data, err := json.Marshal(req)
	if err != nil {
		return
	}
	return w.sendAppChatByte(data)
}

// 发送文本消息
func (w *QyWechat) SendAppChatText(chatId, content string) (err error) {
	return w.sendAppChatMsg(NewTextSendAppChatMessage(chatId, content))
}

// 发送图片消息
func (w *QyWechat) SendAppChatImage(chatId, mediaId string) (err error) {
	return w.sendAppChatMsg(NewImageSendAppChatMessage(chatId, mediaId))
}

// 发送语音消息
func (w *QyWechat) SendAppChatVoice(chatId, mediaId string) (err error) {
	return w.sendAppChatMsg(NewVoiceSendAppChatMessage(chatId, mediaId))
}

// 发送视频消息
func (w *QyWechat) SendAppChatVideo(chatId, mediaId, title, description string) (err error) {
	return w.sendAppChatMsg(NewVideoSendAppChatMessage(chatId, mediaId, title, description))
}

// 发送文件消息
func (w *QyWechat) SendAppChatFile(chatId, mediaId string) (err error) {
	return w.sendAppChatMsg(NewFileSendAppChatMessage(chatId, mediaId))
}

// 发送文本卡片消息
func (w *QyWechat) SendAppChatTextCard(chatId, title, description, urlStr, btnTxt string) (err error) {
	return w.sendAppChatMsg(NewTextCardSendAppChatMessage(chatId, title, description, urlStr, btnTxt))
}

// 发送图文消息
func (w *QyWechat) SendAppChatNews(chatId string, articles []Article) (err error) {
	return w.sendAppChatMsg(NewNewsSendAppChatMessage(chatId, articles))
}

// 发送markdown消息
func (w *QyWechat) SendAppChatMarkDown(chatId, content string) (err error) {
	return w.sendAppChatMsg(NewMarkDownSendAppChatMessage(chatId, content))
}

// ===========================================================

// 构建数据结构
type baseSendAppChatMessage struct {
	ChatId  string `json:"chatid"`
	MsgType string `json:"msgtype"`
}

// 文本
type TextSendAppChatMessage struct {
	baseSendAppChatMessage
	Text Text `json:"text"`
	Safe int  `json:"safe"`
}

func NewTextSendAppChatMessage(chatId, content string) TextSendAppChatMessage {
	return TextSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "text",
		},
		Text{Content: content},
		0,
	}
}

// 图片
type ImageSendAppChatMessage struct {
	baseSendAppChatMessage
	Image Image `json:"image"`
	Safe  int   `json:"safe"`
}

func NewImageSendAppChatMessage(chatId, mediaId string) ImageSendAppChatMessage {
	return ImageSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "image",
		},
		Image{MediaId: mediaId},
		0,
	}
}

// 语音
type VoiceSendAppChatMessage struct {
	baseSendAppChatMessage
	Voice Voice `json:"voice"`
}

func NewVoiceSendAppChatMessage(chatId, mediaId string) VoiceSendAppChatMessage {
	return VoiceSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "voice",
		},
		Voice{MediaId: mediaId},
	}
}

// 视频
type VideoSendAppChatMessage struct {
	baseSendAppChatMessage
	Video Video `json:"video"`
	Safe  int   `json:"safe"`
}

func NewVideoSendAppChatMessage(chatId, mediaId, title, description string) VideoSendAppChatMessage {
	return VideoSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "video",
		},
		Video{
			MediaId:     mediaId,
			Title:       title,
			Description: description,
		},
		0,
	}
}

// 文件
type FileSendAppChatMessage struct {
	baseSendAppChatMessage
	File File `json:"file"`
	Safe int  `json:"safe"`
}

func NewFileSendAppChatMessage(chatId, mediaId string) FileSendAppChatMessage {
	return FileSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "file",
		},
		File{
			MediaId: mediaId,
		},
		0,
	}
}

// 文本卡片
type TextCardSendAppChatMessage struct {
	baseSendAppChatMessage
	TextCard TextCard `json:"textcard"`
	Safe     int      `json:"safe"`
}

func NewTextCardSendAppChatMessage(chatId, title, description, urlStr, btnTxt string) TextCardSendAppChatMessage {
	return TextCardSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "textcard",
		},
		TextCard{
			Title:       title,
			Description: description,
			Url:         urlStr,
			BtnTxt:      btnTxt,
		},
		0,
	}
}

// 图文消息
type NewsSendAppChatMessage struct {
	baseSendAppChatMessage
	News News `json:"news"`
	Safe int  `json:"safe"`
}

func NewNewsSendAppChatMessage(chatId string, articles []Article) NewsSendAppChatMessage {
	return NewsSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "news",
		},
		News{Articles: articles},
		0,
	}
}

// markdown消息
type MarkDownSendAppChatMessage struct {
	baseSendAppChatMessage
	MarkDown MarkDown `json:"markdown"`
}

func NewMarkDownSendAppChatMessage(chatId, content string) MarkDownSendAppChatMessage {
	return MarkDownSendAppChatMessage{
		baseSendAppChatMessage{
			ChatId:  chatId,
			MsgType: "markdown",
		},
		MarkDown{Content: content},
	}
}
